{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "\n",
       "require(['notebook/js/codecell'], function(codecell) {\n",
       "  codecell.CodeCell.options_default.highlight_modes[\n",
       "      'magic_text/x-csrc'] = {'reg':[/^%%microblaze/]};\n",
       "  Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n",
       "      Jupyter.notebook.get_cells().map(function(cell){\n",
       "          if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n",
       "  });\n",
       "});\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from pynq import DefaultIP\n",
    "from pynq import Overlay\n",
    "from pynq import Xlnk\n",
    "import numpy as np\n",
    "import datetime"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "class BinomialTreeDriver(DefaultIP):\n",
    "    def __init__(self, description):\n",
    "        super().__init__(description=description)\n",
    "\n",
    "    bindto = ['xilinx.com:hls:binomial_tree:1.0']\n",
    "\n",
    "    @property\n",
    "    def status(self):\n",
    "        return self.read(0x00)\n",
    "    \n",
    "    @status.setter\n",
    "    def status(self, value):\n",
    "        self.write(0x00, value)\n",
    "\n",
    "    @property\n",
    "    def output(self):\n",
    "        return self.read(0x10)\n",
    "\n",
    "    @output.setter\n",
    "    def output(self, value):\n",
    "        self.write(0x10, value)\n",
    "\n",
    "    @property\n",
    "    def spot_price(self):\n",
    "        return self.read(0x18)\n",
    "\n",
    "    @spot_price.setter\n",
    "    def spot_price(self, value):\n",
    "        self.write(0x18, value)\n",
    "\n",
    "    @property\n",
    "    def strike_price(self):\n",
    "        return self.read(0x20)\n",
    "\n",
    "    @strike_price.setter\n",
    "    def strike_price(self, value):\n",
    "        self.write(0x20, value)\n",
    "\n",
    "    @property\n",
    "    def time_to_maturity(self):\n",
    "        return self.read(0x28)\n",
    "\n",
    "    @time_to_maturity.setter\n",
    "    def time_to_maturity(self, value):\n",
    "        self.write(0x28, value)\n",
    "\n",
    "    @property\n",
    "    def dividend_yield(self):\n",
    "        return self.read(0x30)\n",
    "\n",
    "    @dividend_yield.setter\n",
    "    def dividend_yield(self, value):\n",
    "        self.write(0x30, value)\n",
    "        \n",
    "    @property\n",
    "    def risk_free_rate(self):\n",
    "        return self.read(0x38)\n",
    "\n",
    "    @risk_free_rate.setter\n",
    "    def risk_free_rate(self, value):\n",
    "        self.write(0x38, value)\n",
    "\n",
    "    @property\n",
    "    def volatility(self):\n",
    "        return self.read(0x40)\n",
    "\n",
    "    @volatility.setter\n",
    "    def volatility(self, value):\n",
    "        self.write(0x40, value)\n",
    "\n",
    "    @property\n",
    "    def type_r(self):\n",
    "        return self.read(0x48)\n",
    "    \n",
    "    @type_r.setter\n",
    "    def type_r(self, value):\n",
    "        self.write(0x48, value)\n",
    "\n",
    "    @property\n",
    "    def height(self):\n",
    "        return self.read(0x50)\n",
    "    \n",
    "    @height.setter\n",
    "    def height(self, value):\n",
    "        self.write(0x50, value)\n",
    "        \n",
    "    @property\n",
    "    def n_options(self):\n",
    "        return self.read(0x58)\n",
    "    \n",
    "    @n_options.setter\n",
    "    def n_options(self, value):\n",
    "        self.write(0x58, value)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.604168"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t0 = datetime.datetime.now()\n",
    "overlay = Overlay(\"./overlay/euro_binomial_tree.bit\")\n",
    "BinomialTree = overlay.binomial_tree\n",
    "t1 = datetime.datetime.now()\n",
    "\n",
    "# Time taken in seconds\n",
    "delta = t1 - t0\n",
    "(delta.microseconds / 1000000) + delta.seconds"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "option_data = np.loadtxt(\"option_data.txt\", comments=\"#\", delimiter=\",\", unpack=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "xlnk = Xlnk()\n",
    "if(option_data.ndim > 1):\n",
    "    n_options = len(option_data)\n",
    "    \n",
    "    if n_options > 25:\n",
    "        n_options = 25\n",
    "else:\n",
    "    n_options = 1\n",
    "\n",
    "output = xlnk.cma_array(shape=(n_options), dtype=np.float32)\n",
    "S = xlnk.cma_array(shape=(n_options), dtype=np.float32)\n",
    "K = xlnk.cma_array(shape=(n_options), dtype=np.float32)\n",
    "T = xlnk.cma_array(shape=(n_options), dtype=np.float32)\n",
    "D = xlnk.cma_array(shape=(n_options), dtype=np.float32)\n",
    "r = xlnk.cma_array(shape=(n_options), dtype=np.float32)\n",
    "v = xlnk.cma_array(shape=(n_options), dtype=np.float32)\n",
    "type_r = xlnk.cma_array(shape=(n_options), dtype=np.int32)\n",
    "height = xlnk.cma_array(shape=(n_options), dtype=np.int32)\n",
    "\n",
    "n_options"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "if(option_data.ndim > 1):\n",
    "    for i in range(n_options):\n",
    "        S[i] = option_data[i][0]\n",
    "        K[i] = option_data[i][1]\n",
    "        T[i] = option_data[i][2]\n",
    "        D[i] = option_data[i][3]\n",
    "        r[i] = option_data[i][4]\n",
    "        v[i] = option_data[i][5]\n",
    "        type_r[i] = option_data[i][6]\n",
    "        if(option_data[i][7] > 30000):\n",
    "            height[i] = 30000\n",
    "        elif(option_data[i][7] < 2):\n",
    "            height[i] = 2\n",
    "        else:\n",
    "            height[i] =  option_data[i][7]\n",
    "else:\n",
    "    S[0] = option_data[0]\n",
    "    K[0] = option_data[1]\n",
    "    T[0] = option_data[2]\n",
    "    D[0] = option_data[3]\n",
    "    r[0] = option_data[4]\n",
    "    v[0] = option_data[5]\n",
    "    type_r[0] = option_data[6]\n",
    "    if(option_data[7] > 30000):\n",
    "        height[0] = 30000\n",
    "    elif(option_data[7] < 2):\n",
    "        height[i] = 2\n",
    "    else:\n",
    "        height[0] = option_data[7]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 0 ns, sys: 996 µs, total: 996 µs\n",
      "Wall time: 654 µs\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "ap_start = 1\n",
    "ap_done = 2\n",
    "ap_idle = 4\n",
    "ap_ready = 8\n",
    "\n",
    "BinomialTree.output = output.physical_address\n",
    "BinomialTree.spot_price = S.physical_address\n",
    "BinomialTree.strike_price = K.physical_address\n",
    "BinomialTree.time_to_maturity = T.physical_address\n",
    "BinomialTree.dividend_yield = D.physical_address\n",
    "BinomialTree.risk_free_rate = r.physical_address\n",
    "BinomialTree.volatility = v.physical_address\n",
    "BinomialTree.type_r = type_r.physical_address\n",
    "BinomialTree.height = height.physical_address\n",
    "BinomialTree.n_options = n_options"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 4.51 s, sys: 234 µs, total: 4.51 s\n",
      "Wall time: 4.51 s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "t0 = datetime.datetime.now()\n",
    "status = 0\n",
    "\n",
    "if (BinomialTree.status == ap_idle) or (BinomialTree.status == ap_ready):\n",
    "    BinomialTree.status = ap_start\n",
    "    \n",
    "    while(status != ap_idle):\n",
    "        status = BinomialTree.status\n",
    "\n",
    "t1 = datetime.datetime.now()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4.505873"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Time taken in seconds\n",
    "delta = t1 - t0\n",
    "(delta.microseconds / 1000000) + delta.seconds"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ContiguousArray([ 2.78521299], dtype=float32)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
